<?php
/*
	Aurus CMS - free OOP CMS
	Copyright (C) 2010  Nestor Yanchuk

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 2 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
if (!defined('ROOT')) die();
include (MAINDIR . '/configs/config.db.php');
/**
 * Клас для роботи з базою даних MySql
 * 
 * @package Aurus
 * @author Kvis
 * @copyright 2010
 * @version 1.0
 * @access public
 */
class Mysql implements Core {
	private static $instance = null;
	/**
	 * Return an instance of class
	 *
	 * @return Mysql
	 */
	public static function getInstance(){
		if (self::$instance) {
			return self::$instance;
		} else {
			return self::$instance = new self();
		}
	}
	
	/**
	 * Ресурс з'єднання з БД
	 *
	 * @var resource
	 */
	protected $db = null;

	/**
	 * Логічна змінна яка вказує чи встановлене з'єднання з БД
	 *
	 * @var boolean
	 */
	private $connected = false;

	/**
	 * Кількість запитів до БД
	 *
	 * @var integer
	 */
	private $zQueryCount = 0;

	/**
	 * Масив всіх запитів до БД
	 *
	 * @var array
	 */
	private $zQueries = array();


	/**
	 * Створення з'єднання з БД
	 *
	 */
	function __construct() {
		$this->db = mysql_connect(Config::get('host', 'db'), Config::get('login', 'db'), Config::get('pass', 'db'));

		if (function_exists('mysql_set_charset')) {
			mysql_set_charset('utf8', $this->db);
		} else {
			$this->query("SET NAMES utf8", $this->db);
		}
		
		mysql_select_db(Config::get('database', 'db'), $this->db);
		if ($this->db) $this->connected = true;
	}

	/**
	 * Провірка з'єднання з БД
	 *
	 */
	function check_connection() {
		if (!$this->connected) {
			$this->connect();
		}
	}

	/**
	 * Запит до БД
	 *
	 * @param string $query
	 * @return unknown
	 */
	function query($query) {
		$this->check_connection();
		$this->zQueryCount++;
		$this->zQueries[] = $query;

		if ($res = mysql_query($query, $this->db)) {
			return $res;
		} else {
			die(mysql_errno() . ' - ' . mysql_error() . '<br>'.$query);
		}

	}

	/**
	 * Обробляє ряд результату як асоціативний масив
	 *
	 * @param resource $resource
	 * @return associative array
	 */
	function fetch_assoc($resource) {
		$this->check_connection();
		return mysql_fetch_assoc($resource);
	}

	/**
	 * Повертає масив першого рядка запиту
	 *
	 * @param string $query
	 * @return associative array
	 */
	function getarray($query) {
		$this->check_connection();
		return $this->fetch_assoc($this->query($query));
	}

	/**
	 * Екранує SQL спец-символи для mysql_query
	 *
	 * @param string $string
	 * @return string
	 */
	function escape($string) {
		return addslashes($string);
	}

	/**
	 * Вставка даних в таблицю
	 *
	 * @param string $table - назва таблиці без префіксу
	 * @param string $values - асоціативний масив даних, які потрібно вставити, наприклад:
	 * array(
	 * 		'name'	=>	'якась назва',
	 * 		'value'	=>	'якесь значення'
	 * )
	 */
	function insert($table, $values) {
		foreach ($values as $into => $vals) {
			$int[] = PREFIX . '_' . $table . '.' . $into;
			$val[] = $this->escape((string )$vals);
		}
		$i = implode(',', $int);
		$v = implode("','", $val);

		$this->query("INSERT INTO `" . PREFIX . "_{$table}` ($i) VALUES ('$v')");
	}


	/**
	 * Вибірка даних з БД
	 * 
	 * @param string $table - назва таблиці без префікса
	 * @param string $rows - колонки, які треба вибрати
	 * @param string $condition - умова, без WHERE
	 * @param string $limit - ліміт
	 * @param string $order - порядок сортування, без ORDER BY
	 * @param string $joinTable - назва таблиці з якою треба з'єднати функцією LEFT JOIN
	 * @param array $joinOn - масив з двох колонок , колонкою таблиці і колонкою таблиці з якою потрібно з'єднати
	 * @param bool $calcRows - увімкнення функції SQL_CALC_FOUND_ROWS, по замовчуванню вимкнено
	 * @return
	 */
	function select($table, $rows = '*', $condition = '', $limit = '', $order = '', $joinTable = '', $joinOn = array(), $calcRows = false) {
		$this->check_connection();
		if (!$table) {
			error('"$table" can\'t be empty');
		}
		$q = array();
		$q[] = 'SELECT';
		if ($calcRows) {
			$q[] = 'SQL_CALC_FOUND_ROWS';
		}
		$q[] = $rows;

		$q[] = 'FROM `' . PREFIX . '_' . $table . '`';

		if ($joinTable) {
			$q[] = 'LEFT JOIN `' . PREFIX . '_' . $joinTable . '` ON';
			$q[] = PREFIX . '_' . $table . '.' . $joinOn[1] . '=' . PREFIX . '_' . $joinTable . '.' . $joinOn[0];
		}

		if ($order) {
			$q[] = 'ORDER BY ' . $order;
		}
		if ($condition) {
			$q[] = 'WHERE ' . $condition;
		}
		if ($limit) {
			$q[] = 'LIMIT ' . $limit;
		}

		$query = $this->query(implode(' ' . chr(10), $q));

		$ret = array();
		while ($r = $this->fetch_assoc($query)) {
			$ret[] = $r;
		}
	
		return $ret;
	}

	/**
	 * Оновлення даних в БД
	 * 
	 * @param string $tableName - назва таблиці в якій треба оновити дані
	 * @param string $arUpdate - асоціативний масив array( column => 'new Data')
	 * @param string $where - логічна умова, якщо не задано, то оновиться ВСЯ! таблиця
	 * @return void
	 */
	function update($tableName, $arUpdate, $where = false) {
		$aSet = array();
		foreach ($arUpdate as $fName => $newVal) {
			$aSet[] = PREFIX . '_' . $tableName . '.' . $fName . '=\'' . $this->escape($newVal) . '\'';
		}
		$set = implode(', ', $aSet);
		$sql = "UPDATE `" . PREFIX . "_{$tableName}` SET $set";
		if ($where) {
			$sql .= ' WHERE ' . $where;
		}

		$this->query($sql);
	}


	/**
	 * Видалення даних з БД
	 * 
	 * @param string $fromTable - таблиця з якої будуть видалятись дані
	 * @param string $where - умова видалення, якщо не задано, то оновиться уся таблиця
	 * @return void
	 */
	function delete($fromTable, $where = false) {
		if ($where) {
			$this->query("DELETE FROM `" . PREFIX . "_{$fromTable}` WHERE {$where}");
		} else {
			$this->query("TRUNCATE TABLE `" . PREFIX . "_{$fromTable}`");
		}
	}

	/**
	 * Функція повертає кількість запитів до бази
	 * 
	 * @return int - кількість запитів до бази
	 */
	function getQueryCount() {
		return $this->zQueryCount;
	}
	
		/**
	 * Функція повертає запити до бази
	 * 
	 * @return array - кількість запити до бази
	 */
	function getQueries() {
		return $this->zQueries;
	}


	/**
	 * Функція повертає кількість даних в таблиці за певною умовою
	 * 
	 * @param string $from - назва таблиці
	 * @param string $where - умова
	 * @return int - кількість даних
	 */
	function getCount($from, $where = false) {
		if ($where) {
			$where = ' WHERE ' . $where;
		} else {
			$where = '';
		}
		$c = $this->getarray("SELECT COUNT(*) as count FROM `" . PREFIX . "_{$from}`" . $where);
		return $c['count'];
	}
}
